home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / machines / c16x / machine.c next >
C/C++ Source or Header  |  1999-01-01  |  27KB  |  789 lines

  1. /*  Code generator for SAB c16x microcontrollers.               */
  2.  
  3. #include "supp.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7. /*  Public data that MUST be there.                             */
  8.  
  9. /* Name and copyright. */
  10. char cg_copyright[]="vbcc code-generator for c16x V0.0 (c) in 1998 by Volker Barthelmann";
  11.  
  12. /*  Commandline-flags the code-generator accepts                */
  13. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,
  14.                     0,0,0,0};
  15. char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data",
  16.                            "merge-constants","--","--","--"};
  17. union ppi g_flags_val[MAXGF];
  18.  
  19. /*  Alignment-requirements for all types in bytes.              */
  20. zlong align[16];
  21.  
  22. /*  Alignment that is sufficient for every object.              */
  23. zlong maxalign;
  24.  
  25. /*  CHAR_BIT of the target machine.                             */
  26. zlong char_bit;
  27.  
  28. /*  Sizes of all elementary types in bytes.                     */
  29. zlong sizetab[16];
  30.  
  31. /*  Minimum and Maximum values each type can have.              */
  32. /*  Must be initialized in init_cg().                           */
  33. zlong t_min[32];
  34. zulong t_max[32];
  35.  
  36. /*  Names of all registers.                                     */
  37. char *regnames[MAXR+1]={"noreg","R0","R1","R2","R3","R4","R5","R6","R7",
  38.                         "R8","R9","R10","R11","R12","R13","R14","R15"};
  39.  
  40. /*  The Size of each register in bytes.                         */
  41. zlong regsize[MAXR+1];
  42.  
  43. /*  Type which can store each register. */
  44. struct Typ *regtype[MAXR+1];
  45.  
  46. /*  regsa[reg]!=0 if a certain register is allocated and should */
  47. /*  not be used by the compiler pass.                           */
  48. int regsa[MAXR+1];
  49.  
  50. /*  Specifies which registers may be scratched by functions.    */
  51. int regscratch[MAXR+1]={0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1};
  52.  
  53. struct reg_handle empty_reg_handle={0};
  54.  
  55. /****************************************/
  56. /*  Some private data and functions.    */
  57. /****************************************/
  58.  
  59. static char *bregnames[]={"nobreg","RL0","RL1","RL2","RL3","RL4","RL5","RL6","RL7",
  60.  "e8","e9","e10","e11","e12","e13","e14","e15","e16"
  61. };
  62.  
  63. static long malign[16]=  {1,1,2,2,2,2,2,1,2,1,1,1,2,1};
  64. static long msizetab[16]={0,1,2,2,4,4,8,0,2,0,0,0,2,0};
  65.  
  66. struct Typ ltyp={INT};
  67.  
  68. #define DATA 0
  69. #define BSS 1
  70. #define CODE 2
  71. #define CDATA 3
  72.  
  73. static int section=-1,newobj,scnt;
  74. static char *codename="SCODE\tSECTION CODE WORD PUBLIC 'CPROGRAM'\n",*ecode="SCODE\tends\n",
  75.             *dataname="SDATA\tSECTION DATA WORD PUBLIC\n",*edata="SDATA\tends\n",
  76.             *bssname="SBSS\tSECTION DATA WORD PUBLIC\n",*ebss="SBSS\tends\n",
  77.             *cdataname="SCDATA\tSECTION DATA WORD PUBLIC\n",*ecdata="SCDATA\tends\n";
  78.  
  79. static char sec_end[32];
  80. static int is_const(struct Typ *);
  81. /* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */
  82. static const int sp=1,tp=2,ti=6;
  83. static int is_const(struct Typ *);
  84. static void pr(FILE *,struct IC *);
  85. static void function_top(FILE *,struct Var *,long);
  86. static void function_bottom(FILE *f,struct Var *,long);
  87.  
  88. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  89.  
  90. static long loff,stackoffset,notpopped,dontpop;
  91.  
  92. static char *x_t[]={"?","b","","","","","","","","","","","","","",""};
  93. static char *ccs[]={"z","nz","lt","ge","le","gt"};
  94. static char *logicals[]={"or","xor","and"};
  95. static char *arithmetics[]={"shl","shr","add","sub","mul","div","mod"};
  96. static char *dct[]={"","db","dw","dw","ddw","ddw","ddw","ddw","ddw"};
  97. static pushedsize,pushorder=2;
  98. static char *idprefix="_",*labprefix="l";
  99.  
  100. static struct fpconstlist {
  101.     struct fpconstlist *next;
  102.     int label,typ;
  103.     union atyps val;
  104. } *firstfpc;
  105.  
  106. static int addfpconst(struct obj *o,int t)
  107. {
  108.     struct fpconstlist *p=firstfpc;
  109.     t&=NQ;
  110.     if(g_flags[4]&USEDFLAG){
  111.         for(p=firstfpc;p;p=p->next){
  112.             if(t==p->typ){
  113.                 eval_const(&p->val,t);
  114.                 if(t==FLOAT&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
  115.                 if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) return(p->label);
  116.             }
  117.         }
  118.     }
  119.     p=mymalloc(sizeof(struct fpconstlist));
  120.     p->next=firstfpc;
  121.     p->label=++label;
  122.     p->typ=t;
  123.     p->val=o->val;
  124.     firstfpc=p;
  125.     return(p->label);
  126. }
  127. static long voff(struct obj *p)
  128. {
  129.   if(p->v->offset<0) return loff-zl2l(p->v->offset)+zl2l(p->val.vlong)-stackoffset+pushedsize-2;
  130.   return zl2l(p->v->offset)+zl2l(p->val.vlong)-stackoffset;
  131. }
  132.  
  133. static void probj2(FILE *f,struct obj *p,int t)
  134. /*  Gibt Objekt auf Bildschirm aus                      */
  135. {
  136.   if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,"[");
  137.   if(p->flags&VARADR) fprintf(f,"#");
  138.   if((p->flags&(VAR|REG))==VAR){
  139.     if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  140.       fprintf(f,"[%s+#%ld]",regnames[sp],voff(p));
  141.     }else{
  142.       if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  143.       if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
  144.     fprintf(f,"%sl%ld",labprefix,zl2l(p->v->offset));
  145.       }else{
  146.     fprintf(f,"%s%s",idprefix,p->v->identifier);
  147.       }
  148.     }
  149.   }
  150.   if(p->flags®){
  151.     fprintf(f,"%s",regnames[p->reg]);
  152.   }
  153.   if(p->flags&KONST){
  154.     if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  155.       fprintf(f,"%sl%d",labprefix,addfpconst(p,t));
  156.     }else{
  157.       fprintf(f,"#");printval(f,&p->val,t&NU,0);
  158.     }
  159.   }
  160.   if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,"]");
  161. }
  162.  
  163. static void pr(FILE *f,struct IC *p)
  164. {
  165.  
  166. }
  167. static void function_top(FILE *f,struct Var *v,long offset)
  168. /*  erzeugt Funktionskopf                       */
  169. {
  170.     int i;
  171.     if(section!=CODE){fprintf(f,sec_end);fprintf(f,codename);section=CODE;strcpy(sec_end,ecode);}
  172.     if(v->storage_class==EXTERN) fprintf(f,"\tpublic\t%s%s\n",idprefix,v->identifier);
  173.     fprintf(f,"%s%s\tproc\tfar\n",idprefix,v->identifier);
  174.     for(pushedsize=0,i=1;i<=MAXR;i++){
  175.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  176.             fprintf(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[i]);
  177.             pushedsize+=2;
  178.         }
  179.     }
  180.     if(offset) fprintf(f,"\tsub\t%s,#%ld\n",regnames[sp],offset);
  181. }
  182. static void function_bottom(FILE *f,struct Var *v,long offset)
  183. /*  erzeugt Funktionsende                       */
  184. {
  185.     int i;
  186.     if(offset) fprintf(f,"\tadd\t%s,#%ld\n",regnames[sp],offset);
  187.     for(i=MAXR;i>0;i--){
  188.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  189.             fprintf(f,"\tmov\t%s,[%s+]\n",regnames[i],regnames[sp]);
  190.         }
  191.     }
  192.     fprintf(f,"\trets\n");
  193.     fprintf(f,"%s%s\tendp\n",idprefix,v->identifier);
  194.     if(!strcmp("main",v->identifier)) fprintf(f,"\textern\t__CSTART:far\n");
  195. }
  196. static int is_const(struct Typ *t)
  197. /*  Tests if a type can be placed in the code-section.  */
  198. {
  199.     if(!(t->flags&(CONST|STRINGCONST))){
  200.         do{
  201.             if(t->flags&(CONST|STRINGCONST)) return(1);
  202.             if((t->flags&NQ)!=ARRAY) return(0);
  203.             t=t->next;
  204.         }while(1);
  205.     }else return(1);
  206. }
  207. static int compare_objects(struct obj *o1,struct obj *o2)
  208. {
  209.     if(o1->flags==o2->flags&&o1->am==o2->am){
  210.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  211.             if(!(o1->flags®)||o1->reg==o2->reg){
  212.                 return(1);
  213.             }
  214.         }
  215.     }
  216.     return(0);
  217. }
  218.  
  219. static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
  220. /*  Generates code to move object q (or register qr) into object z (or  */
  221. /*  register zr).                                                       */
  222. {
  223.   int tr;
  224.   t&=NQ;
  225.   if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
  226.   if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
  227.   if(qr)
  228.     tr=qr;
  229.   else{
  230.     if(zr) tr=zr; else tr=ti;
  231.     fprintf(f,"\tmov%s\t%s,",x_t[t],(t==CHAR)?bregnames[tr]:regnames[tr]);
  232.     if(qr) fprintf(f,"%s",(t==CHAR)?bregnames[qr]:regnames[qr]); else probj2(f,q,t);
  233.     fprintf(f,"\n");
  234.   }
  235.   if(tr!=zr){
  236.     fprintf(f,"\tmov%s\t",x_t[t]);
  237.     if(zr) fprintf(f,"%s",(t==CHAR)?bregnames[zr]:regnames[zr]); else probj2(f,z,t);
  238.     fprintf(f,",%s\n",(t==CHAR)?bregnames[tr]:regnames[tr]);
  239.   }
  240. }
  241.  
  242. static void save_result(FILE *f,int r,struct obj *o,int t)
  243. /*  Saves result in register r!=tp to object o. May use tp. */ 
  244. {
  245.   if((o->flags&(REG|DREFOBJ))==DREFOBJ){
  246.     o->flags&=~DREFOBJ;
  247.     move(f,o,0,0,tp,POINTER);
  248.     o->flags|=(DREFOBJ|REG);
  249.     o->reg=tp;
  250.   }
  251.   move(f,0,r,o,0,t);
  252. }
  253.  
  254. static long pof2(zulong x)
  255. /*  Yields log2(x)+1 oder 0. */
  256. {
  257.     zulong p;int ln=1;
  258.     p=ul2zul(1L);
  259.     while(ln<=32&&zulleq(p,x)){
  260.         if(zuleqto(x,p)) return(ln);
  261.         ln++;p=zuladd(p,p);
  262.     }
  263.     return(0);
  264. }
  265.  
  266. /****************************************/
  267. /*  End of private fata and functions.  */
  268. /****************************************/
  269.  
  270.  
  271. int init_cg(void)
  272. /*  Does necessary initializations for the code-generator. Gets called  */
  273. /*  once at the beginning and should return 0 in case of problems.      */
  274. {
  275.     int i;
  276.     /*  Initialize some values which cannot be statically initialized   */
  277.     /*  because they are stored in the target's arithmetic.             */
  278.     maxalign=l2zl(2L);
  279.     char_bit=l2zl(8L);
  280.     for(i=0;i<16;i++){
  281.         sizetab[i]=l2zl(msizetab[i]);
  282.         align[i]=l2zl(malign[i]);
  283.     }
  284.     for(i=1;i<=MAXR;i++){regsize[i]=l2zl(2L);regtype[i]=<yp;}
  285.  
  286.     /*  Initialize the min/max-settings. Note that the types of the     */
  287.     /*  host system may be different from the target system and you may */
  288.     /*  only use the smallest maximum values ANSI guarantees if you     */
  289.     /*  want to be portable.                                            */
  290.     /*  That's the reason for the subtraction in t_min[INT]. Long could */
  291.     /*  be unable to represent -2147483648 on the host system.          */
  292.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
  293.     t_min[CHAR]=l2zl(-128L);
  294.     t_min[SHORT]=l2zl(-32768L);
  295.     t_min[LONG]=zlsub(l2zl(-2147483647L),l2zl(1L));
  296.     t_min[INT]=t_min[SHORT];
  297.     t_max[CHAR]=ul2zul(127L);
  298.     t_max[SHORT]=ul2zul(32767UL);
  299.     t_max[LONG]=ul2zul(2147483647UL);
  300.     t_max[INT]=t_max[SHORT];
  301.     t_max[UNSIGNED|CHAR]=ul2zul(255UL);
  302.     t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
  303.     t_max[UNSIGNED|LONG]=ul2zul(4294967295UL);
  304.     t_max[UNSIGNED|INT]=t_max[UNSIGNED|SHORT];
  305.     /*  Reserve a few registers for use by the code-generator.      */
  306.     regsa[sp]=regsa[tp]=regsa[ti]=1;
  307.     regscratch[sp]=regscratch[tp]=regscratch[ti]=0;
  308.     return(1);
  309. }
  310.  
  311. int freturn(struct Typ *t)
  312. /*  Returns the register in which variables of type t are returned. */
  313. /*  If the value cannot be returned in a register returns 0.        */
  314. {
  315.     int typ=t->flags&NQ;
  316.     if(typ<=POINTER) return 5;
  317.     return 0;
  318. }
  319.  
  320. int regok(int r,int t,int mode)
  321. /*  Returns 0 if register r cannot store variables of   */
  322. /*  type t. If t==POINTER and mode!=0 then it returns   */
  323. /*  non-zero only if the register can store a pointer   */
  324. /*  and dereference a pointer to mode.                  */
  325. {
  326.     t&=NQ;
  327.     if(r==0) return(0);
  328.     if(mode){
  329.       if(r<=4) return 1; else return 0;
  330.     }
  331.     if(t==CHAR&&r>8) return 0;
  332.     if(t<LONG||t==POINTER) return 1;
  333.     return 0;
  334. }
  335.  
  336. int dangerous_IC(struct IC *p)
  337. /*  Returns zero if the IC p can be safely executed     */
  338. /*  without danger of exceptions or similar things.     */
  339. /*  vbcc may generate code in which non-dangerous ICs   */
  340. /*  are sometimes executed although control-flow may    */
  341. /*  never reach them (mainly when moving computations   */
  342. /*  out of loops).                                      */
  343. /*  Typical ICs that generate exceptions on some        */
  344. /*  machines are:                                       */
  345. /*      - accesses via pointers                         */
  346. /*      - division/modulo                               */
  347. /*      - overflow on signed integer/floats             */
  348. {
  349.     int c=p->code;
  350.     if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
  351.         return(0);
  352.     if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
  353.         return(1);
  354.     return(0);
  355. }
  356.  
  357. int must_convert(np p,int t)
  358. /*  Returns zero if code for converting np to type t    */
  359. /*  can be omitted.                                     */
  360. /*  In this generic 32bit RISC cpu pointers and 32bit   */
  361. /*  integers have the same representation and can use   */
  362. /*  the same registers.                                 */
  363. {
  364.     int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
  365.     if(op==tp) return 0;
  366.     if((op==SHORT||op==INT||op==POINTER)&&(tp==SHORT||tp==INT||tp==POINTER))
  367.       return 0;
  368.     return(1);
  369. }
  370.  
  371. void gen_ds(FILE *f,zlong size,struct Typ *t)
  372. /*  This function has to create <size> bytes of storage */
  373. /*  initialized with zero.                              */
  374. {
  375.   fprintf(f,"\tds\t%ld\n",zl2l(size));
  376. }
  377.  
  378. void gen_align(FILE *f,zlong align)
  379. /*  This function has to make sure the next data is     */
  380. /*  aligned to multiples of <align> bytes.              */
  381. {
  382.     if(!zlleq(align,l2zl(1L))) fprintf(f,"\teven\n");
  383. }
  384.  
  385. void gen_var_head(FILE *f,struct Var *v)
  386. /*  This function has to create the head of a variable  */
  387. /*  definition, i.e. the label and information for      */
  388. /*  linkage etc.                                        */
  389. {
  390.     int constflag;
  391.     if(v->clist) constflag=is_const(v->vtyp);
  392.     if(v->storage_class==STATIC){
  393.         if((v->vtyp->flags&NQ)==FUNKT) return;
  394.         if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){
  395.           fprintf(f,sec_end);strcpy(sec_end,edata);
  396.           fprintf(f,dataname);section=DATA;
  397.         }
  398.         if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CDATA){
  399.           fprintf(f,sec_end);strcpy(sec_end,ecdata);
  400.           fprintf(f,cdataname);section=CDATA;
  401.         }
  402.         if(!v->clist&§ion!=BSS){
  403.            fprintf(f,sec_end);strcpy(sec_end,ebss);
  404.            fprintf(f,bssname);section=BSS;
  405.         }
  406.         fprintf(f,"\teven\n%sl%ld\n",labprefix,zl2l(v->offset));
  407.     }
  408.     if(v->storage_class==EXTERN){
  409.         if(v->flags&(DEFINED|TENTATIVE)){
  410.             fprintf(f,"\tpublic\t%s%s\n",idprefix,v->identifier);
  411.             if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){
  412.               fprintf(f,sec_end);strcpy(sec_end,edata);
  413.               fprintf(f,dataname);section=DATA;
  414.             }
  415.             if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=CDATA){
  416.               fprintf(f,sec_end);strcpy(sec_end,ecdata);
  417.               fprintf(f,cdataname);section=CDATA;
  418.             }
  419.             if(!v->clist&§ion!=BSS){
  420.               fprintf(f,sec_end);strcpy(sec_end,ebss);
  421.               fprintf(f,bssname);section=BSS;
  422.             }
  423.             fprintf(f,"\teven\n%s%s\n",idprefix,v->identifier);
  424.         }else{
  425.           fprintf(f,"\textern\t%s%s:far\n",idprefix,v->identifier);
  426.         }
  427.     }
  428. }
  429.  
  430. void gen_dc(FILE *f,int t,struct const_list *p)
  431. /*  This function has to create static storage          */
  432. /*  initialized with const-list p.                      */
  433. {
  434.     fprintf(f,"\t%s\t",dct[t&NQ]);
  435.     if(!p->tree){
  436.         if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
  437.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  438.             unsigned char *ip;
  439.             ip=(unsigned char *)&p->val.vdouble;
  440.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  441.             if((t&NQ)==DOUBLE){
  442.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  443.             }
  444.         }else{
  445.             printval(f,&p->val,t&NU,0);
  446.         }
  447.     }else{
  448.         int m=p->tree->o.flags;
  449.         p->tree->o.flags&=~VARADR;
  450.         probj2(f,&p->tree->o,t&NU);
  451.         p->tree->o.flags=m;
  452.     }
  453.     fprintf(f,"\n");
  454. }
  455.  
  456. /*  The main code-generation routine.                   */
  457. /*  f is the stream the code should be written to.      */
  458. /*  p is a pointer to a doubly linked list of ICs       */
  459. /*  containing the function body to generate code for.  */
  460. /*  v is a pointer to the function.                     */
  461. /*  offset is the size of the stackframe the function   */
  462. /*  needs for local variables.                          */
  463. void gen_code(FILE *f,struct IC *p,struct Var *v,zlong offset)
  464. {
  465.     int c,t,lastcomp=0,reg;
  466.     if(DEBUG&1) printf("gen_code()\n");
  467.     for(c=1;c<=15;c++) regs[c]=regsa[c];
  468.     regs[16]=0;
  469.     loff=((zl2l(offset)+1)/2)*2;
  470.     function_top(f,v,loff);
  471.     stackoffset=notpopped=dontpop=0;
  472.     for(;p;pr(f,p),p=p->next){
  473.         c=p->code;t=p->typf;
  474.         if(c==NOP) continue;
  475.         if(c==SUBPFP) c=SUB;
  476.         if(c==SUBIFP) c=SUB;
  477.         if(c==ADDI2P) c=ADD;
  478.         if(c==ALLOCREG){
  479.             regs[p->q1.reg]=1;
  480.             continue;
  481.         }
  482.         if(c==FREEREG){
  483.             regs[p->q1.reg]=0;
  484.             continue;
  485.         }
  486.         if(notpopped&&!dontpop){
  487.             int flag=0;
  488.             if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
  489.                 fprintf(f,"\tadd\t%s,#%ld\n",regnames[sp],notpopped);
  490.                 stackoffset+=notpopped;notpopped=0;
  491.             }
  492.         }
  493.         if(c==LABEL) {fprintf(f,"%s%d:\n",labprefix,t);continue;}
  494.         if(c==BRA){fprintf(f,"\tjmpr\tcc_uc,%s%d\n",labprefix,t);continue;}
  495.         if(c==BEQ||c==BNE){
  496.           fprintf(f,"\tjmpr\tcc_%s,%s%d\n",ccs[c-BEQ],labprefix,t);
  497.           continue;
  498.         }
  499.         if(c>BNE&&c<BRA){            
  500.             if(lastcomp&UNSIGNED) fprintf(f,"\tjmpr\tcc_u%s,%s%d\n",ccs[c-BEQ],labprefix,t);
  501.                 else              fprintf(f,"\tjmpr\tcc_s%s,%s%d\n",ccs[c-BEQ],labprefix,t);
  502.             continue;
  503.         }
  504.         if(c==MOVETOREG){
  505.             move(f,&p->q1,0,0,p->z.reg,INT);
  506.             continue;
  507.         }
  508.         if(c==MOVEFROMREG){
  509.             move(f,0,p->q1.reg,&p->z,0,INT);
  510.             continue;
  511.         }
  512.  
  513.         if((t&NQ)==LONG) {pric2(stdout,p);ierror(0);}
  514.         if((t&NQ)==FLOAT) {pric2(stdout,p);ierror(0);}
  515.         if((t&NQ)==DOUBLE) {pric2(stdout,p);ierror(0);}
  516.  
  517.         if(isreg(z)) reg=p->z.reg; else reg=ti;
  518.         if(p->q1.flags&DREFOBJ){
  519.           if(p->q1.flags®){
  520.         if(p->q2.flags)
  521.           fprintf(f,"\tmov%s\t%s,[%s]\n",x_t[t&NQ],regnames[reg],regnames[p->q1.reg]);
  522.           }else{
  523.         p->q1.flags&=~DREFOBJ;
  524.         move(f,&p->q1,0,0,tp,POINTER);
  525.         p->q1.flags|=(DREFOBJ|REG);
  526.         p->q1.reg=tp;
  527.         if(p->q2.flags)
  528.           fprintf(f,"\tmov\t%s,[%s]\n",regnames[reg],regnames[tp]);
  529.           }
  530.         }else{
  531.       if(p->q2.flags){
  532.         if(!p->z.flags&&isreg(q1)) reg=p->q1.reg;
  533.         move(f,&p->q1,0,0,reg,t);
  534.       }
  535.         }
  536.         if(p->q2.flags&DREFOBJ){
  537.           if(!(p->q2.flags®)||p->q2.reg>4){
  538.             p->q2.flags&=~DREFOBJ;
  539.             move(f,&p->q2,0,0,tp,POINTER);
  540.             p->q2.flags|=(REG|DREFOBJ);
  541.             p->q2.reg=tp;
  542.           }
  543.         }else if((p->q2.flags&(VAR|REG))==VAR){
  544.       if(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER){
  545.         move(f,&p->q2,0,0,tp,t);
  546.         p->q2.flags|=REG;
  547.         p->q2.reg=tp;
  548.       }
  549.     }
  550.     
  551.         if(c>=CONVCHAR&&c<=CONVULONG){
  552.             int to;
  553.             if(c==CONVCHAR) to=CHAR;
  554.             if(c==CONVUCHAR) to=(UNSIGNED|CHAR);
  555.             if(c==CONVSHORT) to=SHORT;
  556.             if(c==CONVUSHORT) to=(UNSIGNED|SHORT);
  557.             if(c==CONVINT) to=SHORT;
  558.             if(c==CONVUINT) to=(UNSIGNED|SHORT);
  559.             if(c==CONVLONG) to=LONG;
  560.             if(c==CONVULONG) to=(UNSIGNED|LONG);
  561.             if(c==CONVFLOAT) to=FLOAT;
  562.             if(c==CONVDOUBLE) to=DOUBLE;
  563.             if(c==CONVPOINTER) to=(UNSIGNED|INT);
  564.             if((t&NU)==INT) t=SHORT;
  565.             if((t&NU)==(UNSIGNED|INT)||(t&NU)==POINTER) t=(UNSIGNED|INT);
  566.             if((to&NQ)<=SHORT&&(t&NQ)<=SHORT){
  567.                 if((to&NQ)==CHAR){
  568.           if(isreg(q1)||((p->q1.flags&(VAR|DREFOBJ))==VAR&&(p->q1.v->storage_class==STATIC||p->q1.v->storage_class==EXTERN))){
  569.                     fprintf(f,"\tmovb%c\t%s,",(to&UNSIGNED)?'z':'s',regnames[reg]);
  570.                     if(isreg(q1)) fprintf(f,"%s",bregnames[p->q1.reg]); else probj2(f,&p->q1,to);
  571.                     fprintf(f,"\n");
  572.                     save_result(f,reg,&p->z,t);
  573.                     continue;
  574.                   }
  575.                   move(f,&p->q1,0,0,reg,to);
  576.                   if(isreg(z)||((p->z.flags&(VAR|DREFOBJ))==VAR&&(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN))){
  577.                     fprintf(f,"\tmovb%c\t",(to&UNSIGNED)?'z':'s');
  578.                     probj2(f,&p->z,t);fprintf(f,",%s\n",bregnames[reg]);
  579.                     continue;
  580.                   }
  581.           fprintf(f,"\tmovb%c\t%s,%s\n",(to&UNSIGNED)?'z':'s',regnames[reg],bregnames[reg]);
  582.                   save_result(f,reg,&p->z,t);
  583.                 }else{
  584.           if(isreg(q1)&®ok(p->q1.reg,t,0)) reg=p->q1.reg;
  585.           move(f,&p->q1,0,0,reg,to);
  586.           save_result(f,reg,&p->z,t);
  587.         }
  588.                 continue;
  589.             }
  590.             ierror(0);
  591.         }
  592.         if(c==MINUS||c==KOMPLEMENT){
  593.       move(f,&p->q1,0,0,reg,t);
  594.       fprintf(f,"\t%s%s\t%s\n",(c==MINUS?"neg":"cpl"),x_t[t&NQ],regnames[reg]);
  595.       save_result(f,reg,&p->z,t);
  596.       continue;
  597.         }
  598.         if(c==SETRETURN){
  599.             if(p->z.reg){
  600.           move(f,&p->q1,0,0,p->z.reg,t);
  601.         }
  602.             continue;
  603.         }
  604.         if(c==GETRETURN){
  605.             if(p->q1.reg){
  606.           save_result(f,p->q1.reg,&p->z,t);
  607.         }
  608.             continue;
  609.         }
  610.         if(c==CALL){
  611.             int reg;
  612.         if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
  613.           fprintf(f,"%s\n",p->q1.v->fi->inline_asm);
  614.         }else{
  615.           if(p->q1.flags&DREFOBJ){
  616.                 fprintf(f,"\tcalli\tcc_uc");probj2(f,&p->q1,t);
  617.         fprintf(f,"\n");
  618.           }else{
  619.                 fprintf(f,"\tcalls\t");probj2(f,&p->q1,t);
  620.                 fprintf(f,"\n");
  621.           }
  622.         }
  623.             if(!zleqto(l2zl(0L),p->q2.val.vlong)){
  624.           notpopped+=zl2l(p->q2.val.vlong);
  625.           dontpop-=zl2l(p->q2.val.vlong);
  626.           if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){
  627.                 /*  Entfernen der Parameter verzoegern  */
  628.           }else{
  629.         fprintf(f,"\tadd\t%s,#%ld\n",regnames[sp],zl2l(p->q2.val.vlong));
  630.         stackoffset+=zl2l(p->q2.val.vlong);
  631.         notpopped-=zl2l(p->q2.val.vlong);
  632.           }
  633.             }
  634.             continue;
  635.         }
  636.         if(c==ASSIGN||c==PUSH){
  637.             if(c==PUSH) dontpop+=zl2l(p->q2.val.vlong);
  638.             if((t&NQ)>POINTER||!zleqto(p->q2.val.vlong,sizetab[t&NQ])||!zlleq(p->q2.val.vlong,l2zl(4L))){
  639.           ierror(0);
  640.             }
  641.         if(isreg(q1)) reg=p->q1.reg;
  642.             if(c==PUSH){
  643.           move(f,&p->q1,0,0,reg,t);
  644.           fprintf(f,"\tmov%s\t[-%s],%s\n",x_t[t&NQ],regnames[sp],regnames[reg]);
  645.           stackoffset-=zl2l(p->q2.val.vlong);
  646.           continue;
  647.             }
  648.             if(c==ASSIGN){
  649.           move(f,&p->q1,0,0,reg,t);
  650.               if((p->z.flags&DREFOBJ)&&!(p->z.flags®)){
  651.                 if(reg==tp) ierror(0);
  652.                 p->z.flags&=~DREFOBJ;
  653.                 move(f,&p->z,0,0,tp,POINTER);
  654.                 p->z.flags|=(REG|DREFOBJ);
  655.                 p->z.reg=tp;
  656.               }
  657.           move(f,0,reg,&p->z,0,t);
  658.           continue;
  659.             }
  660.             ierror(0);
  661.         }
  662.         if(c==ADDRESS){
  663.       fprintf(f,"\tmov\t%s,%s\n",regnames[reg],regnames[sp]);
  664.       if(voff(&p->q1)) fprintf(f,"\tadd\t%s,#%ld\n",regnames[reg],voff(&p->q1));
  665.       save_result(f,reg,&p->z,POINTER);
  666.       continue;
  667.         }
  668.         if(c==TEST){
  669.             lastcomp=t;
  670.         if(isreg(q1)) reg=p->q1.reg;
  671.         move(f,&p->q1,0,0,reg,t);
  672.         fprintf(f,"\tcmp%s\t%s,#0\n",x_t[t&NQ],regnames[reg]);
  673.         continue;
  674.     }
  675.         if(c==COMPARE){
  676.             lastcomp=t;
  677.         p->q1.flags=REG;p->q1.reg=reg;
  678.             if(isreg(q2)||(p->q1.flags&KONST)){
  679.                 struct IC *b=p->next;
  680.                 struct obj o;
  681.                 o=p->q1;p->q1=p->q2;p->q2=o;
  682.                 while(b&&b->code==FREEREG) b=b->next;
  683.                 if(!b) ierror(0);
  684.                 if(b->code==BLT) b->code=BGT;
  685.                 else if(b->code==BLE) b->code=BGE;
  686.                 else if(b->code==BGT) b->code=BLT;
  687.                 else if(b->code==BGE) b->code=BLE;
  688.             }
  689.             fprintf(f,"\tcmp%s\t",x_t[t&NQ]);
  690.         probj2(f,&p->q1,t);fprintf(f,",");
  691.             probj2(f,&p->q2,t);fprintf(f,"\n");
  692.             continue;
  693.         }
  694.         if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  695.             long ln;
  696.             eval_const(&p->q2.val,t);
  697.             if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
  698.                 if(ln=pof2(vulong)){
  699.                     if(c==MOD){
  700.                         vlong=zlsub(vlong,l2zl(1L));
  701.                         p->code=AND;
  702.                     }else{
  703.                         vlong=l2zl(ln-1);
  704.                         if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
  705.                     }
  706.                     c=p->code;
  707.                     if((t&NU)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  708.                     if((t&NU)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  709.                     if((t&NU)==INT) p->q2.val.vint=zl2zi(vlong);
  710.                     if((t&NU)==LONG) p->q2.val.vlong=vlong;
  711.                     vulong=zl2zul(vlong);
  712.                     if((t&NU)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  713.                     if((t&NU)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  714.                     if((t&NU)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  715.                     if((t&NU)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  716.                 }
  717.             }
  718.         }
  719.         if(c==MOD||c==DIV){
  720.       ierror(0);
  721.     }
  722.         if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)){
  723.             char *s;
  724.             if(c>=OR&&c<=AND) s=logicals[c-OR];
  725.                 else s=arithmetics[c-LSHIFT];
  726.             if(c==RSHIFT&&!(t&UNSIGNED)) s="ashr";
  727.         if((c==MULT&&!isreg(q2))){
  728.           move(f,&p->q2,0,0,tp,t);
  729.           p->q2.flags=REG;
  730.           p->q2.reg=tp;
  731.         }
  732.         if((c==LSHIFT||c==RSHIFT)&&!(p->q2.flags&KONST)&&!isreg(q2)){
  733.           move(f,&p->q2,0,0,tp,t);
  734.           p->q2.flags=REG;
  735.           p->q2.reg=tp;
  736.         }
  737.         fprintf(f,"\t%s%s\t%s,",s,x_t[t&NQ],regnames[reg]);
  738.         probj2(f,&p->q2,t);fprintf(f,"\n");
  739.             if(c==MULT) fprintf(f,"\tmov\t%s,mdl\n",regnames[reg]);
  740.             save_result(f,reg,&p->z,t);
  741.             continue;
  742.         }
  743.         ierror(0);
  744.     }
  745.     if(notpopped){
  746.         fprintf(f,"\tadd\t%s,#%ld\n",regnames[sp],notpopped);
  747.         stackoffset+=notpopped;notpopped=0;
  748.     }
  749.     function_bottom(f,v,loff);
  750. }
  751.  
  752. int shortcut(int code,int typ)
  753. {
  754.     return(0);
  755. }
  756.  
  757. void cleanup_cg(FILE *f)
  758. {
  759.     struct fpconstlist *p;
  760.     unsigned char *ip;
  761.     while(p=firstfpc){
  762.         if(f){
  763.             if(section!=CDATA){
  764.               fprintf(f,sec_end);strcpy(sec_end,ecdata);
  765.               fprintf(f,cdataname);section=CDATA;
  766.             }
  767.         fprintf(f,"\teven\n");
  768.             fprintf(f,"%sl%d\n\tddw\t",labprefix,p->label);
  769.             ip=(unsigned char *)&p->val.vdouble;
  770.             fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
  771.             if((p->typ&NQ)==DOUBLE){
  772.                 fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
  773.             }
  774.             fprintf(f,"\n");
  775.         }
  776.         firstfpc=p->next;
  777.         free(p);
  778.     }
  779.     if(f) fprintf(f,"%s\tREGDEF R0-R15\n\tend\n",sec_end);
  780. }
  781.  
  782. int reg_parm(struct reg_handle *p,struct Typ *t,int mode)
  783. {
  784.   if((t->flags&NQ)>LONG&&(t->flags&NQ)!=POINTER) return 0;
  785.   if(p->gpr>3||mode) return 0;
  786.   return 13+p->gpr++;
  787. }
  788.  
  789.